﻿#ifndef __GETTICKCOUNT_H__
#define __GETTICKCOUNT_H__

#ifdef WIN32
  #define USE_SYSTEM_GETTICKCOUNT     1
  #include <stdint.h>
#else
  #include <stdint.h>
#endif 

#ifdef WIN32
  #include <Windows.h>

  typedef ULONGLONG (WINAPI *LPFN_GETTICKCOUNT64)(VOID);  
  static LPFN_GETTICKCOUNT64 fnGetTickCount64 = (LPFN_GETTICKCOUNT64)GetProcAddress(
    GetModuleHandleA("kernel32"),"GetTickCount64");

#elif __APPLE__
  #include <mach/mach_time.h>

#else
  #include <time.h>
  #include <sys/times.h>
  #include <sys/time.h>
#endif

/**
 * Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC.
 * 单位: 毫秒
 */
static uint64_t gettickcount()
{
#ifdef WIN32
  #if USE_SYSTEM_GETTICKCOUNT
    if (NULL == fnGetTickCount64)
        return GetTickCount();
    else
        return fnGetTickCount64();
  #else
    static LARGE_INTEGER g_Frequency = {0};
    LARGE_INTEGER now;
    if (g_Frequency.QuadPart == 0)
    {
        QueryPerformanceFrequency(&g_Frequency);
    }
    QueryPerformanceCounter(&now);
    return uint64_t(now.QuadPart * 1e3) / g_Frequency.QuadPart;
  #endif //WIN32
#elif __APPLE__
    static mach_timebase_info_data_t timebase;
    if (timebase.denom == 0) 
    {
        // Get the timebase if this is the first time we run.
        // Recommended by Apple's QA1398.
        mach_timebase_info(&timebase);
    }
    return (mach_absolute_time() * timebase.numer / timebase.denom / 1e6);
//#elif __mips__
//    struct timespec ts={0};
//    clock_gettime(CLOCK_REALTIME,&ts);
//    return (ts.tv_sec*1000 + ts.tv_nsec/(1000*1000));
#else
    struct timespec ts={0};
    clock_gettime(CLOCK_MONOTONIC,&ts);
    return (uint64_t)ts.tv_sec * 1e3 + (uint64_t)ts.tv_nsec / 1e6;
#endif
}

//static
//uint64_t gettickcount_ms()
//{
//#ifdef WIN32
//    static LARGE_INTEGER g_Frequency = {0};
//    LARGE_INTEGER now;
//    if (g_Frequency.QuadPart == 0)
//    {
//        QueryPerformanceFrequency(&g_Frequency);
//    }
//    QueryPerformanceCounter(&now);
//    return  uint64_t(now.QuadPart * 1e3) / g_Frequency.QuadPart;
//#elif __APPLE__
//    static mach_timebase_info_data_t timebase;
//    if (timebase.denom == 0) 
//    {
//        // Get the timebase if this is the first time we run.
//        // Recommended by Apple's QA1398.
//        mach_timebase_info(&timebase);
//    }
//    return (mach_absolute_time() * timebase.numer / timebase.denom / 1e6);
//#else
//    struct timespec ts={0};
//    clock_gettime(CLOCK_MONOTONIC,&ts);
//    return (uint64_t)ts.tv_sec * 1e3 + (uint64_t)ts.tv_nsec / 1e6;
//#endif
//}
//
//static
//uint64_t gettickcount_us()
//{
//#ifdef WIN32
//    static LARGE_INTEGER g_Frequency = {0};
//    LARGE_INTEGER now;
//    if (g_Frequency.QuadPart == 0)
//    {
//        QueryPerformanceFrequency(&g_Frequency);
//    }
//    QueryPerformanceCounter(&now);
//    return  uint64_t(now.QuadPart * 1e6) / g_Frequency.QuadPart;
//#elif __APPLE__
//    static mach_timebase_info_data_t timebase;
//    if (timebase.denom == 0) 
//    {
//        // Get the timebase if this is the first time we run.
//        // Recommended by Apple's QA1398.
//        mach_timebase_info(&timebase);
//    }
//    return (mach_absolute_time() * timebase.numer / timebase.denom / 1e3);
//#else
//    struct timespec ts={0};
//    clock_gettime(CLOCK_MONOTONIC,&ts);
//    return (uint64_t)ts.tv_sec * 1e6 + (uint64_t)ts.tv_nsec / 1e3;
//#endif
//}
//
//static
//uint64_t gettickcount_ns()
//{
//#ifdef WIN32
//    static LARGE_INTEGER g_Frequency = {0};
//    LARGE_INTEGER now;
//    if (g_Frequency.QuadPart == 0)
//    {
//        QueryPerformanceFrequency(&g_Frequency);
//    }
//    QueryPerformanceCounter(&now);
//    return uint64_t(now.QuadPart * 1e9) / g_Frequency.QuadPart;
//#elif __APPLE__
//    static mach_timebase_info_data_t timebase;
//    if (timebase.denom == 0) 
//    {
//        // Get the timebase if this is the first time we run.
//        // Recommended by Apple's QA1398.
//        mach_timebase_info(&timebase);
//    }
//    return (mach_absolute_time() * timebase.numer / timebase.denom);
//#else
//    struct timespec ts={0};
//    clock_gettime(CLOCK_MONOTONIC,&ts);
//    return (uint64_t)ts.tv_sec*1e9 + (uint64_t)ts.tv_nsec;
//#endif
//}

#endif //__GETTICKCOUNT_H__

